package cn.eyesea.cc;

import cn.eyesea.cc.config.DomainConfig;
import cn.eyesea.cc.config.GlobalConfig;
import cn.eyesea.cc.entity.FieldInfo;
import cn.eyesea.cc.entity.DomainInfo;
import cn.eyesea.cc.entity.TypeMapper;
import cn.eyesea.cc.tool.GlobalTool;
import cn.eyesea.cc.tool.TimeUtils;
import cn.eyesea.cc.util.ConfigUtil;
import cn.eyesea.cc.util.DBUtil;
import cn.eyesea.cc.util.FileUtil;
import cn.eyesea.cc.util.VelocityUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * 入口
 *
 * @author wanghuilong
 * @version 1.0
 * @date 2021/4/19 4:03 下午
 */
@Slf4j
public class Main {

    static String globalConfigFile = "./globalConfig.properties";

    static String domainJsonFile = "./domain.json";

    /**
     * 导入包时过滤的包前缀
     */
    private static final String FILTER_PACKAGE_NAME = "java.lang";

    public static void main(String[] args) throws IOException {
        GlobalConfig globalConfig = ConfigUtil.getGlobalConfig(globalConfigFile);
        log.info("globalConfig:{}", globalConfig);
        //准备配置
        ConfigUtil.configType(globalConfig);
        //查询数据库表信息
        DBUtil.setDbInfo(globalConfig);
        //读取domain.json配置
        DomainConfig domainConfig = ConfigUtil.getDomainConfig(domainJsonFile);
        JSONArray tableConfig = createDomainJsonConfig(globalConfig);
        System.out.println(tableConfig.toJSONString());
    }

    private static JSONArray createDomainJsonConfig(GlobalConfig globalConfig) {
        List<TypeMapper> typeMapperList = globalConfig.getTypeMapperList();
        List<DomainInfo> tables = DBUtil.getTables();
        JSONArray tableConfig = new JSONArray();
        for (int i = 0; i < tables.size(); i++) {
            DomainInfo tableInfo = tables.get(i);
            List<FieldInfo> fieldInfos = DBUtil.getTableColumnInfo(tableInfo.getTable());
            for (int j = 0; j < fieldInfos.size(); j++) {
                FieldInfo fieldInfo = fieldInfos.get(j);
                for (int k = 0; k < typeMapperList.size(); k++) {
                    TypeMapper typeMapper = typeMapperList.get(k);
                    if (fieldInfo.getDbType().matches(typeMapper.getColumnType())) {
                        fieldInfo.setJavaType(typeMapper.getJavaType());
                    }
                }
            }
            tableInfo.setColumns(fieldInfos);
            tableConfig.add(generateConfig(tableInfo));
        }
        return tableConfig;
    }

    private static JSONObject generateConfig(DomainInfo tableInfo) {
        JSONObject obj = new JSONObject();
        obj.put("name", tableInfo.getName());
        obj.put("table", tableInfo.getTable());
        List<FieldInfo> columnInfoList = tableInfo.getColumns();
        JSONArray columns = new JSONArray();
        for (int j = 0; j < columnInfoList.size(); j++) {
            FieldInfo fieldInfo = columnInfoList.get(j);
            String dbType = fieldInfo.getDbType();
            JSONObject tableColumn = new JSONObject();
            tableColumn.put("field", fieldInfo.getField());
            tableColumn.put("name", fieldInfo.getName());
            tableColumn.put("dbType", dbType);
            tableColumn.put("javaType", fieldInfo.getJavaType());
            tableColumn.put("defaultValue", fieldInfo.getDefaultValue());
            if ("java.lang.String".equals(fieldInfo.getJavaType())) {
                int start = dbType.indexOf("(");
                if (start > -1) {
                    int end = dbType.indexOf(")");
                    Integer len = Integer.valueOf(dbType.substring(start + 1, end));
                    tableColumn.put("maxLen", len);
                } else {
                    tableColumn.put("maxLen", 1024);
                }
            }
            columns.add(tableColumn);
        }
        obj.put("columns", columns);
        return obj;
    }

    private static void generateCode(GlobalConfig globalConfig, DomainInfo tableInfo) {
        Map<String, Object> param = getDefaultParam(globalConfig);
        //创建entity
        param.put("tableInfo", tableInfo);
        param.put("importList", getImportList(tableInfo));
        param.put("package", globalConfig.getBasePackage() + ".dao.entity");
        String generate = VelocityUtils.generate("/template/entity.java.vm", param);
        String filePath = globalConfig.getOutDir() + "/" + (globalConfig.getBasePackage() + ".dao.entity").replaceAll("\\.", "/")
                + "/" + GlobalTool.getInstance().getClassName(tableInfo.getTable()) + ".java";
        log.info("filePath:{}", filePath);
        FileUtil.writeToFile(generate, filePath);
    }


    /**
     * 获取默认参数
     *
     * @return 参数
     */
    private static Map<String, Object> getDefaultParam(GlobalConfig globalConfig) {
        Map<String, Object> param = new HashMap<>(20);
        // 作者
        param.put("author", globalConfig.getAuthor());
        //基础包名
        param.put("basePackage", globalConfig.getBasePackage());
        //工具类
        param.put("tool", GlobalTool.getInstance());
        param.put("time", TimeUtils.getInstance());
        return param;
    }


    /**
     * 获取导入列表
     *
     * @param tableInfo 表信息对象
     * @return 导入列表
     */
    private static Set<String> getImportList(DomainInfo tableInfo) {
        // 创建一个自带排序的集合
        Set<String> result = new TreeSet<>();
        tableInfo.getColumns().forEach(columnInfo -> {
            if (!columnInfo.getJavaType().startsWith(FILTER_PACKAGE_NAME)) {
                result.add(columnInfo.getJavaType());
            }
        });
        return result;
    }

}
